package titt.service.strategy;

import titt.TITTValues;
import titt.error.NuderException;
import titt.head.request.MethodHead;

import titt.io.socket.TITTSocket;

import titt.service.ServicePackage;
import titt.service.content.InternalNuderRequest;
import titt.service.content.InternalNuderResponse;
import titt.service.content.NuderRequest;
import titt.service.content.NuderResponse;
import titt.service.os.ServiceObjectServer;
import titt.service.proxy.server.ServerProxy;

import titt.type.TypedObject;
import titt.type.Types;
import titt.util.ArrayUtil;

public class NuderStrategy implements TITTStrategy {

	public boolean acceptsEncoding(String enc) {
		return true;
	}

	@Override
	public void invokeAndRespond(MethodHead m, ServiceObjectServer sos, ServicePackage pack) {
		String packageID = pack.getPackageID();

		TypedObject[] postargs = {};

		TypedObject ret;
		int status = 200;

		NuderRequest nreq = null;
		try {
			if(m.getHTTPMethod() == TITTValues.POST)
				postargs = new TypedObject[]{new TypedObject(Types.toNative(NuderRequest.class), nreq = new InternalNuderRequest(m, pack.getTITTSocket().getInputStream()).getNuderRequest())};
			ret = sos.getMethodInvoker().call(m.getMethodName(), ArrayUtil.combine(m.getParams(),postargs));
		}
		catch(Exception e) {
			try {
				throw e.getCause();
			}
			catch(NuderException ex) {
				ret = new TypedObject(Types.UNKNOWN, ex.getReponse());
				status = ex.getStatus();
			}
			catch(Throwable ex) {
				ret = new TypedObject(Types.STRING, ""+ex.getMessage());
				status = 418;
			}
		}

		close(pack);

		try {
			if(nreq != null)
				nreq.getContentStream().close();
		}
		catch(Exception e) {}


		if(ret.getObject() == null)
			ret = new TypedObject(Types.STRING, "null");

		TITTSocket ts = null;

		try {

			ts = ServerProxy.get().sync(packageID);

			NuderResponse nuderResp = null;

			if(ret.getObject() instanceof NuderResponse) 
				nuderResp = ret.getObject();
			else
				nuderResp = new NuderResponse(ret.getObject(), status);

			
			InternalNuderResponse inr = new InternalNuderResponse(nuderResp);
			inr.encodeAndWriteToSocket(ts);			

			close(ts);
		}
		catch(Exception e) {
			close(ts);
		}
	}

	private void close(TITTSocket ts) {
		try {
			if(ts != null && !ts.isClosed())
				ts.close();
		}
		catch(Exception e) {}
	}

	private void close(ServicePackage pack) {
		close(pack.getTITTSocket());	
	}

}
